package net.thermetics.fx.services.impl;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;

import javax.xml.namespace.QName;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xquery.XQConnection;
import javax.xml.xquery.XQException;
import javax.xml.xquery.XQExpression;
import javax.xml.xquery.XQSequence;

import net.sf.saxon.xqj.SaxonXQDataSource;
import net.thermetics.fx.auth.GaeUser;
import net.thermetics.fx.model.ForumPost;
import net.thermetics.fx.model.ForumThread;
import net.thermetics.fx.services.ThreadService;
import net.thermetics.fx.util.GAEConnectionManager;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.htmlcleaner.DomSerializer;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class ThreadServiceImpl implements ThreadService {
	private static final String USER_AGENT = "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7";
	
	@Override
	public List<ForumThread> getAllThreads() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public ForumThread getThread(String threadID) throws ClientProtocolException, IOException, ParserConfigurationException, XQException {
		DefaultHttpClient client = new DefaultHttpClient(new GAEConnectionManager(), new BasicHttpParams());
		HttpGet get = new HttpGet("http://www.christianforums.com/" + threadID);
		get.addHeader("User-Agent", USER_AGENT);
		HttpResponse resp = client.execute(get);
		
		HttpEntity ent = resp.getEntity();
		System.out.println("   response: " + resp.getStatusLine());
		
		HtmlCleaner cleaner = new HtmlCleaner();
		TagNode root = cleaner.clean(ent.getContent());
		Node parsedNode = parse(new DomSerializer(cleaner.getProperties(), true).createDOM(root));
		
		ForumThread thread = new ForumThread();
		thread.setTitle(extractTitle(parsedNode));
		thread.setPosts(extractPosts(parsedNode));
		
		return thread;
	}
	
	private Node parse(Node node) throws XQException, FileNotFoundException {
		SaxonXQDataSource xqs = new SaxonXQDataSource();
		XQConnection conn = xqs.getConnection();
		XQExpression expr = conn.createExpression();
		
		expr.bindDocument(new QName("doc"), new DOMSource(node), null);
		
		InputStream query = new FileInputStream("WEB-INF/xquery/thread.xq");

		XQSequence results = expr.executeQuery(query);
		
		if (results.next()) {
			return results.getNode();
		}
		else {
			return null;
		}
	}
	
	private String extractTitle(Node xmlRoot) {
		if (xmlRoot instanceof Element) {
			Element e = (Element)xmlRoot;
			return e.getAttribute("title");
		}
		else {
			return "No title";
		}
	}
	
	private List<ForumPost> extractPosts(Node xmlRoot) {
		List<ForumPost> posts = new ArrayList<ForumPost>();
		
		//each child is a <post>.
		NodeList children = xmlRoot.getChildNodes();
		for (int c = 0 ; c < children.getLength(); c++) {
			Node child = children.item(c);
			try {
				posts.add(extractPost(child));
			} catch (TransformerException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		return posts;
	}
	
	private ForumPost extractPost(Node postNode) throws TransformerException {
		ForumPost post = new ForumPost();
		
		NodeList children = postNode.getChildNodes();
		
        //set up a transformer
        TransformerFactory transfac = TransformerFactory.newInstance();
        Transformer trans = transfac.newTransformer();
        trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        trans.setOutputProperty(OutputKeys.INDENT, "yes");

        //create string from xml tree
        StringWriter sw = new StringWriter();
        StreamResult result = new StreamResult(sw);
        DOMSource source = new DOMSource(children.item(1));
        trans.transform(source, result);
        String xmlString = sw.toString();
        
		post.setUsername(children.item(0).getTextContent());
		post.setContent(xmlString);
		
		return post;
	}

	@Override
	public ForumThread createThread(String threadID) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public ForumThread createThread(String threadID, List<GaeUser> participants) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public boolean updateThread(ForumThread thread) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean deleteThread(String threadID) {
		// TODO Auto-generated method stub
		return false;
	}

}
